package com.lianup.noname.connector;

import com.lianup.noname.processor.HttpProcessor;
import org.apache.catalina.*;

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Stack;
import java.util.concurrent.*;

/**
 * 目前可简单理解为，它只负责接收请求，生成HttpResponse和HttpRequest，然后把这两个扔给http处理器处理
 * lifeCycle用于维护该接口的每个Catalina组件的生命周期
 */
public class HttpConnector implements Runnable, Lifecycle{


    private Container container;

    private boolean stoped;

    private Stack<HttpProcessor> processors = new Stack<>();

    protected int minProcessors = 5;

    protected int maxProcessors = 20;

    private static final ThreadPoolExecutor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(5,10,200, TimeUnit.MILLISECONDS,new ArrayBlockingQueue<Runnable>(5));


    @Override
    public void addLifecycleListener(LifecycleListener lifecycleListener) {
    }

    @Override
    public LifecycleListener[] findLifecycleListeners() {
        return new LifecycleListener[0];
    }

    @Override
    public void removeLifecycleListener(LifecycleListener lifecycleListener) {

    }

    @Override
    public void init() throws LifecycleException {

    }

    public void invoke(){

    }


    /**
     * 这是lifecycle的start（）
     */
    @Override
    public void start(){
        initProcessors();
        THREAD_POOL_EXECUTOR.execute(HttpConnector.this);
//        new Thread(this).start();
    }

    @Override
    public void stop() throws LifecycleException {

    }

    @Override
    public void destroy() throws LifecycleException {

    }

    @Override
    public LifecycleState getState() {
        return null;
    }

    @Override
    public String getStateName() {
        return null;
    }

    @Override
    public void run() {

        while (!stoped) {
            try (ServerSocket serverSocket = new ServerSocket(8080, 1, InetAddress.getByName("127.0.0.1"))) {
                while (true) {
                    Socket socket = serverSocket.accept();
                    HttpProcessor process = createProcessor();
                    if(process == null){
                        socket.close();
                    }else {
                        process.assign(socket);
                        new Thread(process).start();

                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public HttpProcessor createProcessor(){
        if(!processors.empty()){
            HttpProcessor processor = processors.pop();
            processor.setConnector(this);
            return processor;
        }
        return null;
    }


    public void initProcessors(){
        int curProcessors = 0;
        while(curProcessors < minProcessors){
            if((maxProcessors > 0) && (curProcessors >= maxProcessors)){
                break;
            }
            HttpProcessor process = new HttpProcessor();
            recycleProcessor(process);
            curProcessors++;
        }
    }

    public void recycleProcessor(HttpProcessor httpProcessor){
        processors.push(httpProcessor);
    }

    public Container getContainer() {
        return container;
    }

    public void setContainer(Container container) {
        this.container = container;
    }
}
